package com.mini.mybatis.executor;

import com.mini.mybatis.executor.parameter.DefaultParameterHandler;
import com.mini.mybatis.executor.parameter.ParameterHandler;
import com.mini.mybatis.executor.resultset.DefaultResultSetHandler;
import com.mini.mybatis.executor.resultset.ResultSetHandler;
import com.mini.mybatis.mapping.BoundSql;
import com.mini.mybatis.mapping.MappedStatement;
import com.mini.mybatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 简单执行器实现 - 提供基础的SQL执行功能
 */
public class SimpleExecutor implements Executor {
    
    private static final Logger logger = LoggerFactory.getLogger(SimpleExecutor.class);
    
    private final Configuration configuration;
    private final boolean autoCommit;
    private boolean closed;
    private Connection connection;
    
    public SimpleExecutor(Configuration configuration, boolean autoCommit) {
        this.configuration = configuration;
        this.autoCommit = autoCommit;
        this.closed = false;
    }
    
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter) throws SQLException {
        BoundSql boundSql = ms.getBoundSql();
        return doQuery(ms, parameter, boundSql);
    }
    
    @Override
    public int update(MappedStatement ms, Object parameter) throws SQLException {
        BoundSql boundSql = ms.getBoundSql();
        return doUpdate(ms, parameter, boundSql);
    }
    
    @Override
    public void commit(boolean required) throws SQLException {
        if (closed) {
            throw new SQLException("执行器已关闭");
        }
        if (required) {
            if (connection != null && !connection.getAutoCommit()) {
                logger.debug("提交JDBC连接");
                connection.commit();
            }
        }
    }
    
    @Override
    public void rollback(boolean required) throws SQLException {
        if (closed) {
            throw new SQLException("执行器已关闭");
        }
        if (required) {
            if (connection != null && !connection.getAutoCommit()) {
                logger.debug("回滚JDBC连接");
                connection.rollback();
            }
        }
    }
    
    @Override
    public void clearLocalCache() {
        // 简单执行器没有缓存，无需清理
    }
    
    @Override
    public void close(boolean forceRollback) {
        try {
            try {
                rollback(forceRollback);
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
        } catch (SQLException e) {
            logger.warn("关闭连接时出现异常", e);
        } finally {
            connection = null;
            closed = true;
        }
    }
    
    @Override
    public boolean isClosed() {
        return closed;
    }
    
    /**
     * 执行查询操作
     */
    @SuppressWarnings("unchecked")
    private <E> List<E> doQuery(MappedStatement ms, Object parameter, BoundSql boundSql) throws SQLException {
        PreparedStatement stmt = null;
        try {
            Connection connection = getConnection();
            stmt = prepareStatement(connection, boundSql.getSql());
            
            // 设置参数
            setParameters(stmt, parameter, boundSql, ms);
            
            // 执行查询
            stmt.executeQuery();
            
            // 处理结果集
            return handleResultSet(stmt, ms);
        } finally {
            closeStatement(stmt);
        }
    }
    
    /**
     * 执行更新操作
     */
    private int doUpdate(MappedStatement ms, Object parameter, BoundSql boundSql) throws SQLException {
        PreparedStatement stmt = null;
        try {
            Connection connection = getConnection();
            stmt = prepareStatement(connection, boundSql.getSql());
            
            // 设置参数
            setParameters(stmt, parameter, boundSql, ms);
            
            // 执行更新
            return stmt.executeUpdate();
        } finally {
            closeStatement(stmt);
        }
    }
    
    /**
     * 获取数据库连接
     */
    private Connection getConnection() throws SQLException {
        if (connection == null || connection.isClosed()) {
            connection = configuration.getDataSource().getConnection();
            connection.setAutoCommit(autoCommit);
        }
        return connection;
    }
    
    /**
     * 准备SQL语句
     */
    private PreparedStatement prepareStatement(Connection connection, String sql) throws SQLException {
        logger.debug("准备执行SQL: {}", sql);
        return connection.prepareStatement(sql);
    }
    
    /**
     * 设置参数
     */
    private void setParameters(PreparedStatement stmt, Object parameter, BoundSql boundSql, MappedStatement ms) throws SQLException {
        ParameterHandler parameterHandler = new DefaultParameterHandler(ms, parameter, boundSql);
        parameterHandler.setParameters(stmt);
    }
    
    /**
     * 处理结果集
     */
    private <E> List<E> handleResultSet(PreparedStatement stmt, MappedStatement ms) throws SQLException {
        ResultSetHandler resultSetHandler = new DefaultResultSetHandler(configuration, ms);
        return resultSetHandler.handleResultSets(stmt);
    }
    
    /**
     * 关闭语句
     */
    private void closeStatement(PreparedStatement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                logger.warn("关闭PreparedStatement时出现异常", e);
            }
        }
    }
}